package com.i360day.invoker.common;

import com.i360day.invoker.exception.HttpInvokerException;
import org.springframework.util.Assert;

import java.net.URI;
import java.net.URISyntaxException;

/**
 * @author liju.z
 */
public class HttpInvokerUrlUtils {

    public static String getAddress(String url) {
        try {
            return getAddress(new URI(url));
        } catch (URISyntaxException e) {
            return getAddress(URI.create(String.format("http://%s", url)));
        }
    }

    public static String getAddress(URI uri) {
        return String.format("%s:%s", uri.getHost(), getPort(uri.toString()));
    }

    /**
     * <p> 拼接URL    <p>
     *
     * <p> @author: 胡.青牛   <p>
     *
     * <p> @Date:   2019/5/10 13:58   <p>
     *
     * <p> @return:      <p>
     **/
    public static String getAssembleUrl(String... values) {
        if (StringUtils.isArrayEmpty(values)) {
            return "";
        }
        StringBuilder bUrl = new StringBuilder("http://");
        for (String key : values) {
            if (StringUtils.isNotEmpty(key)) {
                bUrl.append(key).append("/");
            }
        }

        return bUrl.substring(0, bUrl.length() - 1);
    }

    /**
     * <p> @Description: 获取URL   <p>
     *
     * <p> @author: 胡.青牛   <p>
     *
     * <p> @Date:   2019/5/13 0013 11:22   <p>
     *
     * <p> @param null     <p>
     *
     * <p> @return:      <p>
     **/
    public static final String getUrl(String url, String contextPath, Class<?> clazz) {
        if (StringUtils.isEmpty(contextPath)) {
            contextPath = "";
        } else if (!contextPath.startsWith("/")) {
            contextPath = HttpInvokerRemoteConstant.SEPARATOR + contextPath;
        }
        String baseUrl = clazz == null ? splicingRemoteUrl(url, contextPath) : splicingRemoteUrl(url, contextPath, clazz);
        if (baseUrl.startsWith("http://") || baseUrl.startsWith("https://") || baseUrl.startsWith("ws://") || baseUrl.startsWith("wss://")) {
            return baseUrl;
        } else if (baseUrl.startsWith("/")) {
            return "http:/" + baseUrl;
        } else {
            return "http://" + baseUrl;
        }
    }

    /**
     * <p> @Description: 获取bean命名规则   <p>
     *
     * <p> @author: 胡.青牛   <p>
     *
     * <p> @Date:   2019/5/10 0010 16:01   <p>
     *
     * <p> @param null     <p>
     *
     * <p> @return:      <p>
     **/
    private static String splicingRemoteUrl(String descUrl, String contextPath, Class<?> clazz) {
        Assert.isTrue(StringUtils.isNotEmpty(descUrl), "name is null");
        try {
            StringBuilder urlBuilder = new StringBuilder();
            if (descUrl.startsWith("http://") || descUrl.startsWith("https://") || descUrl.startsWith("ws://") || descUrl.startsWith("wss://")) {
                URI url = new URI(descUrl);
                int port = getPort(url.toString());
                if (StringUtils.isEmpty(url.getPath())) {
                    return urlBuilder
                            .append(url)
                            .append(appendUrl(
                                    contextPath,
                                    HttpInvokerRemoteConstant.FIXED_URL,
                                    clazz == null ? "" : ClassUtils.getClassNameToLowerCaseFirstOne(clazz.getSimpleName())
                            ))
                            .toString();
                } else if (url.getPath().startsWith("/")) {
                    return urlBuilder
                            .append(url.getScheme()).append("://").append(url.getHost()).append(":").append(port)
                            .append(appendUrl(
                                    contextPath,
                                    HttpInvokerRemoteConstant.FIXED_URL,
                                    url.getPath(),
                                    clazz == null ? "" : ClassUtils.getClassNameToLowerCaseFirstOne(clazz.getSimpleName())
                            ))
                            .toString();
                }
                return urlBuilder
                        .append(url.getScheme()).append("://").append(url.getHost()).append(":").append(port)
                        .append(appendUrl(
                                contextPath,
                                HttpInvokerRemoteConstant.FIXED_URL,
                                url.getPath(),
                                clazz == null ? "" : ClassUtils.getClassNameToLowerCaseFirstOne(clazz.getSimpleName())
                        ))
                        .toString();

            } else {
                if (descUrl.startsWith("/")) {
                    return splicingRemoteUrl("http:/" + replaceUrl(descUrl), contextPath, clazz);
                } else {
                    return splicingRemoteUrl("http://" + replaceUrl(descUrl), contextPath, clazz);
                }
            }
        } catch (Exception e) {
        }

        return descUrl;
    }


    /**
     * <p> @Description: 获取bean命名规则   <p>
     *
     * <p> @author: 胡.青牛   <p>
     *
     * <p> @Date:   2019/5/10 0010 16:01   <p>
     *
     * <p> @param null     <p>
     *
     * <p> @return:      <p>
     **/
    public static final String splicingRemoteUrl(String descUrl, String contextPath) {
        return splicingRemoteUrl(descUrl, contextPath, null);
    }

    public static String replaceUrl(String descUrl) {
        if (StringUtils.isEmpty(descUrl)) return descUrl;

        return descUrl.replaceAll("\\\\", "/").replaceAll("////", "/").replaceAll("///", "/").replaceAll("//", "/");
    }

    /**
     * <p> @author liju.z <p>
     *
     * <p> @Description 拼接 <p>
     *
     * <p> @Date  17:11 <p>
     *
     * <p> @Param [urls] <p>
     **/
    private static String appendUrl(Object... urls) {
        StringBuilder builder = new StringBuilder();
        for (Object url : urls) {
            if (StringUtils.isNotEmpty(url)) {
                builder.append(url).append("/");
            }
        }
        return replaceUrl(builder.substring(0, builder.length() - 1));
    }

    /**
     * <p> @Description: 获取端口 <p>
     *
     * <p> @author: 胡.青牛 <p>
     *
     * <p> @Date:   2019/6/13 0013 17:48 <p>
     *
     * <p> @param null   </p>
     *
     * <p> @return:    <p>
     **/
    public static int getPort(String descUrl) {
        if (StringUtils.isEmpty(descUrl)) throw new HttpInvokerException("descUrl is null");
        else if (!descUrl.startsWith("http") && !descUrl.startsWith("https://") && !descUrl.startsWith("ws://") && !descUrl.startsWith("wss://")) {
            descUrl = "http://" + descUrl;
        }
        URI url = URI.create(descUrl);
        if (url.getPort() <= 0) {
            if (descUrl.startsWith("http://") || descUrl.startsWith("ws://")) return 80;
            else if (descUrl.startsWith("https://") || descUrl.startsWith("wss://")) return 443;
        }
        return url.getPort();
    }

    /**
     * <p> @author liju.z <p>
     *
     * <p> @Description 指定ip替换url <p>
     *
     * <p> @Date  16:57 <p>
     *
     * <p> @Param [uri, ip] <p>
     *
     * <p> @return [uri, ip] <p>
     **/
    public static URI reconstructURIWithIp(String uri, String ip) {
        return reconstructURIWithIp(URI.create(uri), ip);
    }

    public static URI reconstructURIWithIp(URI uri, String ip) {
        return reconstructURIWithIp(uri, ip, "");
    }

    /**
     * <p> @author liju.z <p>
     *
     * <p> @Description 指定ip项目名替换 <p>
     *
     * <p> @Date  16:57 <p>
     *
     * <p> @Param [uri, ip, contextPath] <p>
     *
     * <p> @return [uri, ip, contextPath] <p>
     **/
    public static URI reconstructURIWithIp(URI uri, String ip, String contextPath) {
        String scheme = uri.getScheme();
        if (null == scheme) {
            if (uri.toString().startsWith("/")) {
                scheme = "http";
            } else {
                if (uri.getPort() <= 0) {
                    if (uri.toString().startsWith("http://")) {
                        scheme = "http";
                    } else if (uri.toString().startsWith("https://")) {
                        scheme = "https";
                    }
                } else {
                    scheme = scheme.startsWith("http") ? scheme : "http";
                }
            }
        }
        StringBuilder sb = new StringBuilder();
        sb.append(scheme).append("://").append(ip).append(contextPath).append(uri.getPath());
        if (StringUtils.isNotEmpty(uri.getRawQuery())) {
            sb.append("?").append(uri.getRawQuery());
        }
        return URI.create(sb.toString());
    }
}
